﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace Alderamin.Core
{
    /// <summary>
    /// Handles the non-encrypted http connection
    /// </summary>
    public sealed class HttpHandler : HttpHandlerBase
    {
        #region Private Fields
        private IWebProxy _proxy;

        private string _mainScriptUrl;

        private const int DEFAULT_BUFFER_SIZE = 8192;
        #endregion

        #region Public Properties
        /// <summary>
        /// The web proxy used to send and receive the data
        /// </summary>
        public IWebProxy Proxy
        {
            get
            {
                return _proxy;
            }
            set
            {
                _proxy = value;
            }
        }

        /// <summary>
        /// The url of the script which handles the combined requests
        /// </summary>
        public string MainScriptUrl
        {
            get
            {
                return _mainScriptUrl;
            }
            set
            {
                _mainScriptUrl = value;
            }
        }
        #endregion

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the HttpsHandler class with the specified url
        /// </summary>
        /// <param name="mainScriptUrl">The script that handles the request</param>
        public HttpHandler(string mainScriptUrl)
        {
            this.MainScriptUrl = mainScriptUrl;
            this.Proxy = null;
        }
        #endregion

        #region Public Methods

        /// <summary>
        /// Send the http request, will block until all the data has been received
        /// </summary>
        /// <param name="reqBody">The original request body</param>
        /// <param name="writeBackStream">A network stream used for data write-back</param>
        /// <param name="hostport">The host (with port number) to connect</param>
        /// <returns>True if the given network stream is vaild;otherwise, false</returns>
        public bool SendRequest(Byte[] reqBody, NetworkStream writeBackStream, string hostport)
        {
            if (null == writeBackStream || !writeBackStream.CanRead || !writeBackStream.CanWrite)
                return false;

            string url = _mainScriptUrl + String.Format("?hp={0}", base.GetBase64String(hostport));
            HttpWebRequest req = base.CreatePostRequest(url, _proxy, null);

            if (null == req) 
                return false;

            req.ContentLength = reqBody.Length;
            try
            {
                req.GetRequestStream().Write(reqBody, 0, reqBody.Length);
                req.GetRequestStream().Close();
                using (Stream respStream = req.GetResponse().GetResponseStream())
                {
                    Byte[] respBuffer = new Byte[DEFAULT_BUFFER_SIZE];
                    int BytesRead;
                    while ((BytesRead = respStream.Read(respBuffer, 0, respBuffer.Length)) != 0)
                    {
                        if (writeBackStream.CanWrite)
                        {
                            writeBackStream.Write(respBuffer, 0, BytesRead);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            catch (IOException) { }
            catch (WebException) { }

            writeBackStream.Close();

            return true;
        }

        #endregion
    }
}
